// @Desc:
// @CreateTime: 2020/10/8
package user

import (
    "github.com/gin-gonic/gin"
    "math"
    "mycrm.com/config"
    . "mycrm.com/controller"
    mlog "mycrm.com/log"
    . "mycrm.com/module"
    "mycrm.com/module/menu"
    "mycrm.com/module/role"
    "mycrm.com/module/user"
    "mycrm.com/utils"
    "net/http"
    "strconv"
)

// login
func Login(c *gin.Context) {
    var userInfo user.CrmUser
    if err := c.BindJSON(&userInfo); err != nil {
        mlog.Log.Error("c.BindJSON(userInfo) is failed, err: ", err)
        return
    }
    mlog.Log.Infof("%s is login", userInfo.Username)
    var hasNum int64 // 大于 0 则有该用户
    resp := Response{
        Status: 1,
        Msg:    "登录成功",
    }
    Db.Model(&user.CrmUser{}).Where("username = ? AND password = ?", userInfo.Username, userInfo.Password).Count(&hasNum)
    if hasNum == 0 { // 登录信息不正确
        resp.Status = 0
        resp.Msg = "用户名或密码错误"
    } else { // 查询是否启用
        var (
            res      user.CrmUser
            resNum   int64 // 用于判断是否有值
            visitUrl string
            roleId   int
        )
        Db.Find(&res, "username = ? AND password = ? AND status = 1", userInfo.Username, userInfo.Password).Count(&resNum)
        mlog.Log.Info("resNum: ", resNum)
        if resNum == 0 {
            resp.Status = 0
            resp.Msg = "请联系管理员启用账号"
        } else { // 获取该用户登录成功的第一个 url
            Db.Model(&user.CrmUser2role{}).Where("user_id = ?", res.ID).Select("role_id").Scan(&roleId)
            Db.Table("crm_role2menu AS r2u").Joins("JOIN crm_menu AS m ON r2u.menu_id = m.id").Where("r2u.role_id = ? AND m.parent_id > 0", roleId).Select("m.url").Limit(1).Scan(&visitUrl)
        }
        loginToken, err := utils.GenerateToken(userInfo.Username, userInfo.Password)
        if err != nil {
            resp.Data = "系统错误, 请联系管理员"
        } else {
            resp.Data = map[string]interface{}{"uid": res.ID, "name": res.Name, "token": loginToken, "token_expire": config.Configs.AuthConf.TokenExpire,"role_id": roleId, "visit_url": visitUrl}
        }
    }
    c.JSON(http.StatusOK, &resp)
}

// register
func Register(c *gin.Context) {
    var userInfo user.CrmUser
    if err := c.BindJSON(&userInfo); err != nil {
        mlog.Log.Error("c.BindJSON(userInfo) is failed, err: ", err)
        return
    }
    mlog.Log.Infof("%s is register", userInfo.Username)
    resp := Response{
        Status: 1,
        Msg:    "注册成功",
    }
    // 先查询用户名是否存在
    var hasNum int64
    Db.Model(&user.CrmUser{}).Where("username = ?", userInfo.Username).Count(&hasNum)
    if hasNum > 0 {
        resp.Status = 0
        resp.Msg = "用户名已存在"
    } else {
        // 将注册的用户的权限都设置为 员工
        userInfo.User2Role = []user.CrmUser2role{user.CrmUser2role{RoleId: userInfo.RoleId}}
        Db.Create(&userInfo)
    }
    c.JSON(200, resp)
}

// user list
func List(c *gin.Context) {
    pageStr := c.Query("cur_page")
    pageNum, _ := strconv.Atoi(pageStr)
    name := c.Query("search_name")
    username := c.Query("search_username")
    statusStr := c.Query("search_status")
    groupId := c.Query("search_groupId")
    statusNum, _ := strconv.Atoi(statusStr)
    tx := Db.Table("crm_user as u").
        Joins("LEFT JOIN crm_user2role as u2r ON u.id = u2r.user_id").
        Joins("LEFT JOIN crm_role as r ON u2r.role_id = r.id").
        Joins("LEFT JOIN crm_usergroup as ug ON u.group_id = ug.id")
    // 姓名查询
    if name != "" {
        tx.Where("u.name = ?", name)
    }
    // 用户名
    if username != "" {
        tx.Where("u.username = ?", username)
    }
    // 状态
    if statusStr != "" {
        tx.Where("u.status = ?", statusNum)
    }
    // 分组 id
    if groupId != "" {
        tx.Where("u.group_id = ?", groupId)
    }
    var (
        pageSize int = 10 // 每页显示
        userInfo []map[string]interface{}
        total    int64 // 总条数
    )
    tx.Count(&total).Select("u.*, r.name as role_name, r.id as role_id, ug.group_name as group_name").Limit(pageSize).Offset((pageNum - 1) * pageSize).Scan(&userInfo)
    // mlog.Log.Info("total: ", total)
    totalPage := int(math.Ceil(float64(total) / float64(pageSize)))
    // mlog.Log.Info("totalPage: ", totalPage)
    // mlog.Log.Info("respUserInfo: ", userInfo)
    resp := &Response{
        Status:      1,
        Data:        &userInfo,
        Total:       int(total),
        CurrentPage: pageNum,
        TotalPage:   totalPage,
    }
    c.JSON(http.StatusOK, resp)
}

// edit user
func Edit(c *gin.Context) {
    var userInfo user.CrmUser
    if err := c.BindJSON(&userInfo); err != nil {
        mlog.Log.Error("c.BindJSON(userInfo) is failed, err: ", err)
        return
    }
    mlog.Log.Infof("%s is edit", userInfo.Username)
    resp := Response{
        Status: 1,
        Msg:    "修改成功",
    }
    if err := Db.Model(&user.CrmUser{}).Where("id = ?", userInfo.ID).Updates(userInfo).Error; err != nil {
        mlog.Log.Error("Db.Model(&user.CrmUser{}).Updates(userInfo).Error is failed, err: ", err)
        resp.Status = 0
        resp.Msg = "修改失败"
    } else { // 更新成后, 修改 role 关联
        Db.Model(&user.CrmUser2role{}).Where("user_id = ?", userInfo.ID).Update("role_id", userInfo.RoleId)
    }
    c.JSON(http.StatusOK, resp)

}

// user del
func Del(c *gin.Context) {
    delUid := c.Param("delUid")
    // 用于判断该用户是否具有删除条件
    curUserId := c.Param("curUserId")
    mlog.Log.Info("delUid: ", delUid)
    resp := Response{
        Status: 1,
        Msg:    "success",
    }
    var roleIdSlice []uint8
    Db.Table("crm_user2role").Select("role_id").Where("user_id = ?", curUserId).Scan(&roleIdSlice)
    // mlog.Log.Info("roleIdSlice: ", roleIdSlice)
    hasDelAuth := false
    for _, roleId := range roleIdSlice {
        if roleId == 1 { // 1 为管理员权限
            hasDelAuth = true
            break
        }
    }
    if !hasDelAuth {
        resp.Status = 0
        resp.Msg = "你没有删除权限"
    } else {
        Db.Delete(&user.CrmUser{}, delUid)
        // 删除关联数据
        Db.Delete(&user.CrmUser2role{}, "user_id = ?", delUid)
    }
    c.JSON(http.StatusOK, &resp)
}

// 获取角色
func GetRoleInfo(c *gin.Context) {
    var (
        roleInfo []role.Role
    )
    Db.Select("id,name").Find(&roleInfo)
    mlog.Log.Info("resp: ", roleInfo)
    resp := Response{
        Status: 1,
        Data:   roleInfo,
    }
    c.JSON(http.StatusOK, resp)
}

// 根据 uid 判断其该显示的菜单
func ShowMenu(c *gin.Context) {
    uid := c.Param("uid")
    // todo 现在只做了是否显示系统管理

    var roleId int
    resp := Response{
        Status: 1,
    }
    // 管理员 和 最高领导才有
    Db.Model(&user.CrmUser2role{}).Select("role_id").Where("user_id = ?", uid).Scan(&roleId)
    resp.Data = roleId
    c.JSON(http.StatusOK, &resp)

}

// 获取所有设计师
func GetDesginer(c *gin.Context) {
    uid := c.Query("uid")
    resp := &Response{
        Status: 1,
    }
    if uid != "" { // 根据 uid 查询单个人的
        var name string
        Db.Model(&user.CrmUser{}).Where("id = ?", uid).Select("name").Scan(&name)
        resp.Data = name
    } else {
        var allDesginer []map[string]interface{}
        Db.Model(&user.CrmUser{}).Select("id, name").Scan(&allDesginer)
        resp.Data = allDesginer
    }

    c.JSON(http.StatusOK, &resp)
}

// 根据 uid 获取菜单
func GetMenus(c *gin.Context) {
    roleId := c.Param("roleId")
    // 查询所有菜单权限
    var (
        menus []menu.CrmMenu
        resp []menu.Menus
    )
    Db.Table("crm_role2menu AS r2u").Joins("LEFT JOIN crm_menu AS m ON r2u.menu_id = m.id").Where("r2u.role_id = ?", roleId).Scan(&menus)
    // mlog.Log.Info("menus: ", menus)
    resp = mergeMenu(menus)
    // respJson, _ := json.Marshal(resp)
    // mlog.Log.Info("resp: ", string(respJson))
    c.JSON(http.StatusOK, Response{
        Status: 1,
        Data:   &resp,
    })
}

// 获取菜单
func mergeMenu(menus []menu.CrmMenu) []menu.Menus {
    respMenus := make([]menu.Menus, 0, 10)
    for _, parentNode := range menus {
        if parentNode.ParentId != 0 { // 为根节点
            continue
        }
        curNode := menu.Menus{
            Parent:   menu.CrmMenu{MyBaseModel: MyBaseModel{ID: parentNode.ID}, Name: parentNode.Name, ClassIcon: parentNode.ClassIcon},
            Children: make([]menu.CrmMenu, 0, 5),
        }
        for _, sonNode := range menus {
            if sonNode.ParentId == 0 { // 为根节点
                continue
            }
            if parentNode.ID == sonNode.ParentId {
                children := menu.CrmMenu{
                    MyBaseModel: MyBaseModel{ID: sonNode.ID},
                    Name:        sonNode.Name,
                    Url:         sonNode.Url,
                }
                curNode.Children = append(curNode.Children, children)
            }
        }
        respMenus = append(respMenus, curNode)
    }
    return respMenus
}
